package modelo;

import excepciones.XMLUnserializeException;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import modelo.Motor;

import java.lang.reflect.Constructor;

import org.jdom.DataConversionException;
import org.jdom.Element;
import org.jdom.Attribute;
import org.jdom.filter.ContentFilter;

import extras.xml.NumericAttribute;
import extras.xml.SerializableXML;


/** 
 * el auto observa a su propio motor
 */
public class Auto extends Observable implements Observer {
 	private double velocidad;
    private Motor motor;
    private Ruedas ruedas;
    private Pista pista;
	private double distanciaRecorrida;
	
	public Auto(Motor motor, Ruedas ruedas){
		this.velocidad = 0;
		this.motor = motor;
		this.ruedas = ruedas;
		//this.pista = null;
		this.distanciaRecorrida = 0;
		this.motor.addObserver(this);
	}
	
	/**
	 * Se crea un auto a partir del elemento xml recibido.
	 *  
	 * @param xmlElement elemento xml que representa al auto
	 * @throws XMLUnserializeException si alguno de los valores del elemento
	 * xml es invalido
	 */
	public Auto(Element xmlElement) throws XMLUnserializeException {
//		try {
//			this.velocidad = 0;
////			this.motor = motor;
////			this.ruedas = ruedas;
//			this.pista = null;
//			this.distanciaRecorrida = 0;
//			this.motor.addObserver(this);
//		}
//		catch (XMLUnserializeException e) {
//			throw new XMLUnserializeException("No pudo crearse el auto desde el elemento xml. " + "Auto" + " : " + e.getMensaje());
//		}
	}
	
	/**
	 * Devuelve un elemento xml que representa al auto.
	 * @return elemento xml que representa al auto
	 */
	public Element toXML() {
		Element xmlElement = new Element("auto");
		
//		Iterator<Componente> it = getComponentesConectados().iterator();
//		while (it.hasNext()) {
//			xmlElement.addContent(it.next().toXML());
//		}
		
		return xmlElement;
	}
	
	public void update(Observable o, Object args){
		/* formula: posicionFinal = posicionInicial + velocidad * tiempo */
		distanciaRecorrida += velocidad * Convertir.mX_a_X(Cronometro.INTERVALO_DE_TIEMPO);
		
		/* la velocidad del auto depende del danio de sus ruedas */
		velocidad = motor.getVelocidad() * (1 - ruedas.getDanio());
		
//		System.out.print("distanciaRecorrida: ");
//		System.out.println(distanciaRecorrida);
//		
//		System.out.print("velocidadActualizada: ");
//		System.out.println(velocidad);
//		
//		System.out.print("getDanio: ");
//		System.out.println(ruedas.getDanio());
//		
//		System.out.println("------------------------------");
		
		
		/* si la distancia recorrida hace que al auto le corresponda el siguiente casillero
		 * se mueve al siguiente */
		if (velocidad != 0)
			if (this.pista.getPosicionEnLargo() < (int) distanciaRecorrida)
				this.pista.moverAutoHaciaAdelante();
		
		notificarObservadores();
	}
	
	public void acelerar() {
		this.motor.acelerar();
    }
	
    public void mantenerVelocidad(){
    	this.motor.aceleracionCte();
    }
    
    public void frenar() {
    	this.motor.frenar();
    }
    
	public void moverHaciaLaDerecha(){
		if(velocidad > 0)
			this.pista.moverAutoHaciaLaDerecha();
		notificarObservadores();
	}
	
	public void moverHaciaLaIzquierda(){
		if(velocidad > 0)
			this.pista.moverAutoHaciaLaIzquierda();
		notificarObservadores();
	}
	
	public int getPosicionEnAncho(){
		return this.pista.getPosicionEnAncho();
	}
	
	public int getPosicionEnLargo(){
		return this.pista.getPosicionEnLargo();
	}
	
	public double getVelocidad() {
		return this.velocidad;
	}
	   
    public Ruedas getRuedas(){
    	return ruedas;
    }
    
    public void notificarObservadores(){
    	setChanged();
    	notifyObservers();
    }

	public void setPista(Pista pista) {
		this.pista = pista;
		
	}

	public void colocarEnPista(Pista pista) {
		pista.colocarAuto(this);
	}
	public void reiniciar(){
		this.motor.reiniciar();
		this.velocidad = 0;
		this.ruedas.reiniciar();
		this.pista = null;
		this.distanciaRecorrida = 0;
	}
}
